package cn.hiapi.core.utils;


import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author : AdinZ  1454269@qq.com
 * @Project: Common
 * @Description:
 * @date Date : 2018年12月01日 13:58
 **/

public class DateUtils {

    public static final String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_YYYY_MM_DD = "yyyy-MM-dd";
    public static final String FORMAT_YYYY_MM = "yyyy-MM";
    public static final String FORMAT_YYYY = "yyyy";
    public static final String FORMAT_YYYY_MM_DD_HH = "yyyy-MM-dd HH";
    public static final String FORMAT_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";


    private static SimpleDateFormat format = new SimpleDateFormat(FORMAT_FULL, Locale.CHINA);

    private static TimeZone timeZone = TimeZone.getTimeZone("GMT+0800");


    /***
     * 自定义时间,格式, 格式化
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(timeZone);
        return simpleDateFormat.format(date);
    }

    public static String format(long time, String format) {
        return format(new Date(time), format);
    }

    public static String format(String format) {
        return format(new Date(), format);
    }

    public static Date parse(String date, String format) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        simpleDateFormat.setTimeZone(timeZone);
        return simpleDateFormat.parse(date);
    }


    /***
     * 当前时间格式化
     * @return
     */
    public static String format() {
        return format(new Date());
    }

    /**
     * 时间格式化 2018-11-11 12:12:12
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        format.setTimeZone(timeZone);
        return format.format(date);
    }

    public static String format(long time) {
        return format(new Date(time));
    }

    /***
     * 获取年月 2018-11
     * @param date 时间
     * @return 2018-11
     */
    public static String formatYearMonth(Date date) {
        return format(date, "yyyy-MM");
    }

    /**
     * 获取当前时间的年月
     *
     * @return
     */
    public static String formatYearMonth() {
        return formatYearMonth(new Date());
    }


    public static Date todayStart(int day) {
        Calendar currentDate = new GregorianCalendar();
        currentDate.setTimeZone(timeZone);
        currentDate.set(Calendar.HOUR_OF_DAY, 0);
        currentDate.set(Calendar.MINUTE, 0);
        currentDate.set(Calendar.SECOND, 0);
        currentDate.set(Calendar.MILLISECOND, 0);
        currentDate.add(Calendar.DATE, day);
        return currentDate.getTime();
    }

    public static Date todayStart(Date date) {
        Calendar currentDate = new GregorianCalendar();
        currentDate.setTime(date);
        currentDate.setTimeZone(timeZone);
        currentDate.set(Calendar.HOUR_OF_DAY, 0);
        currentDate.set(Calendar.MINUTE, 0);
        currentDate.set(Calendar.SECOND, 0);
        currentDate.set(Calendar.MILLISECOND, 0);
        return currentDate.getTime();
    }

    public static Date todayEnd(Date date) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    public static Date todayEnd(int day) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        calendar.add(Calendar.DATE, day);
        Date date = calendar.getTime();
        return date;
    }

    public static Date getDate() {
        Calendar cal = Calendar.getInstance(timeZone);
        return cal.getTime();
    }

    public static long getTimestamp() {
        return getDate().getTime();
    }


    public static Date getWeekStart(Date date) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return calendar.getTime();
    }

    public static Date getWeekEnd(Date date) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.setTime(addDay(date, 7));
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        return calendar.getTime();
    }

    public static Date getMonthStart(Date date, int month) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(date);
        cal.set(Calendar.MONDAY, cal.get(Calendar.MONDAY) + month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    public static Date getHourStart(Date date, int hour) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + hour);
        cal.set(Calendar.MINUTE, cal.getActualMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getActualMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getActualMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    public static Date getHourEnd(Date date, int hour) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + hour);
        cal.set(Calendar.MINUTE, cal.getActualMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getActualMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getActualMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }


    public static Date getMonthStart(Date date) {
        return getMonthStart(date, 0);
    }

    public static Date getMonthStart(int month) {
        return getMonthStart(new Date(), month);
    }


    public static Date getMonthEnd(Date date) {
        return getMonthEnd(date, 0);
    }

    public static Date getMonthEnd(Date date, int month) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(date);
        cal.set(Calendar.MONDAY, cal.get(Calendar.MONDAY) + month);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    public static Date getMonthEnd(int month) {
        return getMonthEnd(new Date(), month);
    }

    /**
     * 获取本月天数
     *
     * @param date
     * @return
     */
    public static int getMonthDayCount(Date date) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static Date getYearStart(int year) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR) + year, cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTime();
    }

    public static Date getYearEnd(int year) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR) + year, cal.getActualMaximum(Calendar.MONDAY), cal.getActualMaximum(Calendar.DAY_OF_MONTH), 0, 0, 0);
//        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    public static Date toDate(String date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        sdf.setTimeZone(timeZone);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date toDate(int day) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.add(Calendar.DATE, day);
        Date date = calendar.getTime();
        return date;
    }

    public static Date toDate(String date) {
        return toDate(date, "yyyy-MM-dd HH:mm:ss");
    }


    public static Date addYear(int year) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR) + year, cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return cal.getTime();
    }

    public static Calendar getCalendar() {
        return Calendar.getInstance(timeZone);
    }

    public static Date addMonth(int month) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH) + month, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return cal.getTime();
    }


    public static int getHour() {
        Calendar cal = Calendar.getInstance(timeZone);

        return cal.get(Calendar.HOUR_OF_DAY);
    }


    public static long addDay(int day) {
        return DateUtils.day(day).getTime();
    }

    public static Date day(int day) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH) + day, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return cal.getTime();
    }

    public static long addDay(long time, int day) {
        return addDay(new Date(time), day).getTime();
    }

    public static Date addDay(Date date, int day) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTime(date);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH) + day, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return cal.getTime();
    }

    /**
     * 当前时间加x分钟
     *
     * @param minute 分钟
     * @return
     */
    public static Date addMinute(int minute) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE) + minute, cal.get(Calendar.SECOND));
        return cal.getTime();
    }

    public static long addMinute(long time, int minute) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTimeInMillis(time);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE) + minute, cal.get(Calendar.SECOND));
        return cal.getTimeInMillis();
    }

    /**
     * 当前时间加x小时
     *
     * @param hour
     * @return
     */
    public static Date addHour(int hour) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY) + hour, cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND));
        return cal.getTime();
    }

    public static long addHour(long time, int hour) {
        Calendar cal = Calendar.getInstance(timeZone);
        cal.setTimeInMillis(time);

        cal.set(cal.get(Calendar.YEAR),
                cal.get(Calendar.MONDAY),
                cal.get(Calendar.DAY_OF_MONTH),
                cal.get(Calendar.HOUR_OF_DAY) + hour,
                cal.get(Calendar.MINUTE),
                cal.get(Calendar.SECOND)
        );
        return cal.getTimeInMillis();
    }


    /**
     * 返回今日星期   星期天  =7
     *
     * @return
     */
    public static int getWeekOfDate() {
        return getWeekOfDate(new Date());
    }

    /***
     * 返回星期  星期天 =7
     * @param date
     * @return
     */
    public static int getWeekOfDate(Date date) {
        Calendar cal = new Calendar.Builder().setInstant(date).setTimeZone(timeZone).build();
        int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (week == 0) return 7;
        return week;
    }

    public static int getWeekOfDate(long time) {
        return getWeekOfDate(new Date(time));
    }


    /**
     * 获取几号
     *
     * @param date
     * @return
     */
    public static int getDay(Date date) {
        Calendar cal = new Calendar.Builder().setInstant(date).setTimeZone(timeZone).build();
        return cal.get(Calendar.DAY_OF_MONTH);
    }


    public static boolean isWorkTime(Date date) {
        int week = getWeekOfDate(date);
        Calendar cal = new Calendar.Builder().setInstant(date).build();
        cal.setTimeZone(timeZone);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (week == 0 || week == 6) {
            return false;
        } else {
            if (hour < 9 || hour >= 17) return false;
            else return true;
        }
    }

    public static long getNextWeekTuesDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.setFirstDayOfWeek(Calendar.TUESDAY);
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        calendar.add(Calendar.DATE, calendar.getFirstDayOfWeek() - day + 7);
        return calendar.getTimeInMillis();
    }


    public static long now() {
        return new Date().getTime();
    }


    public static long getToDayHour(int hour) {
        Calendar calendar = Calendar.getInstance(timeZone);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime().getTime();
    }


    /**
     * 对比时间
     *
     * @param time 格式  HH:mm /HH:mm:ss
     * @return
     */
    public static long getTime(String time, String format) throws ParseException {
        final Calendar today = DateUtils.getCalendar();
        final Date parse = DateUtils.parse(time, format);
        final Calendar calendar = DateUtils.getCalendar();
        calendar.setTime(parse);
        calendar.set(today.get(Calendar.YEAR), today.get(Calendar.MONTH), today.get(Calendar.DAY_OF_MONTH));
        return calendar.getTimeInMillis();
    }

    /**
     * 计算2个时间相差几天
     *
     * @param min
     * @param max
     * @return
     */
    public static int getDay(long min, long max) {
        return (int) ((max - min) / (24 * 60 * 60 * 1000L));
    }
}
